import util from "@/util/paint";

function Marker(data, context, type) {
  this.type = type
  this.data = data
  this.context = context
  this.scale = 1
  this.center = []
  this.icon = ''
  this.region = []
  this.font = 'Microsoft YaHei-Bold'
  this.animationId = null
  this.animations = {}
  this.actived = false
  this.activedIcon = ''
}

Marker.prototype.drawIcon = function () {
}
Marker.prototype.render = function (scale, center) {
  this.region = []
  this.scale = scale
  this.center = center
  this.drawIcon(this.scale, this.center)
}
Marker.prototype.animate = function (name, region, stepFn) {
  this.animations[name] = {region, stepFn}
  util.stopAnimation(this.animationId)
  let regions = Object.keys(this.animations).map(key => this.animations[key].region).map(item => [item[0], item[1], item[0] + item[2], item[1] + item[3]]),
    snapshotArea = [Math.min(...regions.map(item => item[0])), Math.min(...regions.map(item => item[1])),
      Math.max(...regions.map(item => item[2])), Math.max(...regions.map(item => item[3]))],
    snapshot = null, mainStepFn = () => {
      util.stopAnimation(this.animationId)
      if (snapshot) this.context.putImageData(snapshot, snapshotArea[0], snapshotArea[1], 0, 0, snapshotArea[2] - snapshotArea[0], snapshotArea[3] - snapshotArea[1])
      snapshot = this.context.getImageData(snapshotArea[0], snapshotArea[1], snapshotArea[2] - snapshotArea[0], snapshotArea[3] - snapshotArea[1])
      for (let n in this.animations) {
        let item = this.animations[n]
        if (item.stepFn && item.stepFn instanceof Function) item.stepFn()
      }
      this.animationId = util.startAnimation(mainStepFn)
    }
  this.animationId = util.startAnimation(mainStepFn)
}

function Marker1(data, context) {
  Marker.call(this, data, context, 1)
  this.glow = null
  this.light = null
}

Marker1.prototype = {...Marker.prototype}
Marker1.prototype.constructor = Marker1
Marker1.prototype.drawIcon = function () {
  if (this.icon && this.icon instanceof Image) {
    let iconRenderWidth = util.dynamicPX(this.icon.width / 2) * this.scale, iconRenderHeight = util.dynamicPX(this.icon.height / 2) * this.scale,
      region = [this.center[0] - iconRenderWidth / 2, this.center[1], iconRenderWidth, iconRenderHeight]
    this.context.drawImage(this.icon, 0, 0, this.icon.width, this.icon.height, ...region)
    this.region.push(region)
    if (this.data.jixin_disaster_id > 0) this.drawWarn()
    else this.drawTitle()
  } else {
    let img = new Image()
    // img.src = require(`@/assets/image/map-marker-icon.${this.data.online_status == 2 ? 'fault' : this.data.online_status == 1 ? 'online' : 'offline'}.png`)
    img.src = require(`@/assets/img/homeicon.png`)
    img.onload = event => {
      this.icon = img
      this.drawIcon()
    }
  }
}
Marker1.prototype.drawTitle = function () {
  const factors = [
    util.dynamicPX(4) * this.scale,  //圆点半径
    util.dynamicPX(10) * this.scale, //圆点右间隔
    util.dynamicPX(6) * this.scale, //名称文字右间隔
    util.dynamicPX(10) * this.scale, //状态文字右间隔
    util.dynamicPX(16) * this.scale, //右侧箭头宽度
    util.dynamicPX(8) * this.scale, //右侧箭头高度
    util.dynamicPX(5) * this.scale, //上下内边距
    util.dynamicPX(16) * this.scale, //方位箭头宽度
    util.dynamicPX(8) * this.scale, //方位箭头高度
    util.dynamicPX(8) * this.scale, //阴影模糊半径
    util.dynamicPX(16) * this.scale, //名称文本字号
    util.dynamicPX(14) * this.scale, //状态文本字号
  ]
  this.drawTitleBg(factors)
  let region = this.region[this.region.length - 1]
  if (this.data.online_status > 0) {
    this.drawTitleDot(factors[0], [region[0] + factors[0], region[1] + (region[3] - factors[0] * 2) / 2 + factors[0]])
    this.drawTitleArrow([region[0] + region[2], region[1] + region[3] / 2], [factors[4], factors[5]])
  }
  this.context.save()

  let name = this.data.name
  let nameFontSize = factors[10]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameTextMetrics = this.context.measureText(name)
  this.context.fillStyle = this.data.online_status == 2 ? '#909399' : '#0D1B38'
  this.context.translate(region[0] + (this.data.online_status == 0 ? 0 : factors[0] * 2 + factors[1]),
    region[1] + region[3] - factors[6] - nameTextMetrics.actualBoundingBoxDescent)
  this.context.fillText(name, 0, 0)

  let status = this.data.online_status == 2 ? '[异常]' : this.data.online_status == 1 ? '[在线]' : '[离线]'
  let statusFontSize = factors[11]
  this.context.font = `${statusFontSize}px ${this.font}`
  this.context.fillStyle = this.data.online_status == 2 ? '#EE9715' : this.data.online_status == 1 ? '#4BAA84' : '#0D1B38'
  this.context.fillText(status, nameTextMetrics.width + factors[2], -((nameFontSize - statusFontSize) / 2))

  this.context.restore()
}
Marker1.prototype.drawTitleBg = function (factors) {
  this.context.save()

  let name = this.data.name
  let nameFontSize = factors[10]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameWidth = this.context.measureText(name).width

  let status = this.data.online_status == 2 ? '[异常]' : this.data.status == 1 ? '[在线]' : '[异常]'
  let statusFontSize = factors[11]
  this.context.font = `${statusFontSize}px ${this.font}`
  let statusWidth = this.context.measureText(status).width

  let width = (this.data.online_status == 0 ? 0 : factors[0] * 2)  //圆点直径
    + (this.data.online_status == 0 ? 0 : factors[1])  //圆点右间隔
    + nameWidth  //地址文字宽度
    + factors[2]  //地址文字右间隔
    + statusWidth //状态文字宽度
    + (this.data.online_status == 0 ? 0 : factors[3])  //状态文字右间隔
    + (this.data.online_status == 0 ? 0 : factors[4])  //右侧箭头宽度
  let height = nameFontSize
    + factors[6] * 2  //上下内边距
  let radius = height / 2
  let direction = [factors[7], factors[8]]  //方位箭头尺寸

  this.context.beginPath()
  this.context.moveTo(...this.center)
  this.context.lineTo(this.center[0] - direction[0] / 2, this.center[1] - direction[1])
  this.context.lineTo(this.center[0] - width / 2, this.center[1] - direction[1])
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1] - direction[1], this.center[0] - width / 2 - radius, this.center[1] - direction[1] - radius, radius)
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1] - direction[1] - height, this.center[0] - width / 2, this.center[1] - direction[1] - height, radius)
  this.context.lineTo(this.center[0] + width / 2, this.center[1] - direction[1] - height)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1] - direction[1] - height, this.center[0] + width / 2 + radius, this.center[1] - direction[1] - radius, radius)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1] - direction[1], this.center[0] + width / 2, this.center[1] - direction[1], radius)
  this.context.lineTo(this.center[0] + direction[0] / 2, this.center[1] - direction[1])
  this.context.lineTo(...this.center)
  this.context.closePath()
  this.region.push([this.center[0] - width / 2, this.center[1] - direction[1] - height, width, height])
  this.context.fillStyle = 'white'
  this.context.shadowColor = this.data.online_status == 2 ? 'rgba(219,178,16,0.5)' : this.data.online_status == 1 ? 'rgba(13,161,126,0.5)' : 'rgba(13,71,161,0.5)'
  this.context.shadowBlur = factors[9]
  this.context.fill()
  this.context.restore()
}
Marker1.prototype.drawTitleDot = function (radius, center) {
  this.context.save()
  this.context.fillStyle = this.data.online_status == 2 ? '#EE9715' : this.data.online_status == 1 ? '#4BAA84' : 'rgba(255,255,255,0)'
  this.context.beginPath()
  this.context.arc(...center, radius, 0, Math.PI * 2, false)
  this.context.closePath()
  this.context.fill()
  this.context.restore()
}
Marker1.prototype.drawTitleArrow = function (center, size) {
  this.context.save()
  this.context.lineWidth = util.dynamicPX(4) * this.scale
  this.context.miterLimit = util.dynamicPX(4) * this.scale
  this.context.strokeStyle = this.data.online_status == 2 ? '#909399' : this.data.online_status == 1 ? '#0D1B38' : 'rgba(255,255,255,0)'
  this.context.beginPath()
  this.context.moveTo(center[0], center[1] - size[1] / 2)
  this.context.lineTo(center[0] - size[0] / 2, center[1] + size[1] / 2)
  this.context.lineTo(center[0] - size[0], center[1] - size[1] / 2)
  this.context.stroke()
  this.context.restore()
}
Marker1.prototype.drawWarn = function () {
  const factors = [
    util.dynamicPX(16) * this.scale,  //圆角半径
    util.dynamicPX(6) * this.scale, //名称文字右间隔
    util.dynamicPX(8) * this.scale, //灾情文字下间隔
    util.dynamicPX(6) * this.scale, //灾情图标右间隔
    util.dynamicPX(2) * this.scale, //电池线条宽度
    util.dynamicPX(8) * this.scale, //电池线条高度
    util.dynamicPX(10) * this.scale, //方位箭头上间隔
    util.dynamicPX(10) * this.scale, //方位箭头宽度
    util.dynamicPX(5) * this.scale, //方位箭头高度
    util.dynamicPX(8) * this.scale, //阴影模糊半径
    util.dynamicPX(14) * this.scale, //名称文本字号
    util.dynamicPX(30) * this.scale, //灾情图标字号
    util.dynamicPX(20) * this.scale, //灾情文本字号
    util.dynamicPX(16) * this.scale, //日期文本字号
  ]
  this.drawWarnBg(factors)
  let region = this.region[this.region.length - 1]  
  this.drawWarnBattery([factors[4], factors[5]], [region[0] + region[2] - factors[0], region[1] + factors[0]])
  this.drawWarnLamp([region[0] + region[2] / 2, region[1]])
  this.drawWarnGlow()
  this.context.save()
  this.context.fillStyle = 'white'

  let name = this.data.name + (this.data.online_status == 2 ? '(异常)' : this.data.online_status == 1 ? '(在线)' : '(离线)')
  let nameFontSize = factors[10]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameTextMetrics = this.context.measureText(name)
  let maxH = Math.max(nameFontSize, factors[4] * 4 + factors[5])
  this.context.translate(region[0] + factors[0], region[1] + factors[0] + maxH)
  this.context.fillText(name, 0, -(maxH - nameFontSize) / 2 - nameTextMetrics.actualBoundingBoxDescent)
  this.context.translate(0, factors[2] * 2)

  let icon = "\ue628"
  let iconFontSize = factors[11]
  this.context.font = `${iconFontSize}px iconfont`
  let iconTextMetrics = this.context.measureText(icon)

  let disaster = this.data.disaster_name
  let disasterFontSize = factors[12]
  this.context.font = `bold ${disasterFontSize}px ${this.font}`
  let disasterTextMetrics = this.context.measureText(disaster)

  let time = this.data.disaster_time
  let timeFontSize = factors[13]
  this.context.font = `${timeFontSize}px ${this.font}`
  let timeTextMetrics = this.context.measureText(time)

  this.context.font = `${iconFontSize}px iconfont`
  this.context.fillText(icon, 0, (disasterFontSize + factors[2] + timeFontSize - iconFontSize) / 2 + iconFontSize - iconTextMetrics.actualBoundingBoxDescent)
  this.context.translate(iconTextMetrics.width + factors[3], disasterFontSize - disasterTextMetrics.actualBoundingBoxDescent)
  this.context.font = `bold ${disasterFontSize}px ${this.font}`
  this.context.fillText(disaster, 0, 0)
  this.context.translate(0, timeFontSize - timeTextMetrics.actualBoundingBoxDescent + factors[2])
  this.context.font = `${timeFontSize}px ${this.font}`
  this.context.fillText(time, 0, 0)

  this.context.restore()

  this.context.save()
  this.context.fillStyle = 'white'
  this.context.beginPath()
  this.context.moveTo(this.center[0], this.center[1] - factors[0])
  this.context.lineTo(this.center[0] - factors[7] / 2, this.center[1] - factors[0] - factors[8])
  this.context.lineTo(this.center[0] + factors[7] / 2, this.center[1] - factors[0] - factors[8])
  this.context.closePath()
  this.context.fill()
  this.context.restore()
}
Marker1.prototype.drawWarnBg = function (factors) {
  this.context.save()

  let name = this.data.name + (this.data.online_status == 2 ? '(异常)' : this.data.online_status == 1 ? '(在线)' : '(离线)')
  let nameFontSize = factors[10]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameWidth = this.context.measureText(name).width

  let icon = "\ue628"
  let iconFontSize = factors[11]
  this.context.font = `${iconFontSize}px iconfont`
  let iconWidth = this.context.measureText(icon).width

  let disaster = this.data.disaster_name
  let disasterFontSize = factors[12]
  this.context.font = `${disasterFontSize}px ${this.font}`
  let disasterWidth = this.context.measureText(disaster).width

  let time = this.data.disaster_time
  let timeFontSize = factors[13]
  this.context.font = `${timeFontSize}px ${this.font}`
  let timeWidth = this.context.measureText(time).width

  let width = Math.max(nameWidth + factors[1] + factors[4] * 12,
    iconWidth + factors[3] + disasterWidth,
    iconWidth + factors[3] + timeWidth)
  let height = Math.max(nameFontSize, factors[4] * 4 + factors[5]) + factors[2] * 2 + disasterFontSize + factors[2] + timeFontSize + factors[6] + factors[8]
  let radius = factors[0]

  this.context.beginPath()
  this.context.moveTo(...this.center)
  this.context.lineTo(this.center[0] - width / 2, this.center[1])
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1], this.center[0] - width / 2 - radius, this.center[1] - radius, radius)
  this.context.lineTo(this.center[0] - width / 2 - radius, this.center[1] - radius - height)
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1] - radius * 2 - height, this.center[0] - width / 2, this.center[1] - radius * 2 - height, radius)
  this.context.lineTo(this.center[0] + width / 2, this.center[1] - radius * 2 - height)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1] - radius * 2 - height, this.center[0] + width / 2 + radius, this.center[1] - radius - height, radius)
  this.context.lineTo(this.center[0] + width / 2 + radius, this.center[1] - radius)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1], this.center[0] + width / 2, this.center[1], radius)
  this.context.closePath()
  this.region.push([this.center[0] - width / 2 - radius, this.center[1] - height - radius * 2, width + radius * 2, height + radius * 2])
  this.context.fillStyle = '#E23A2C'
  this.context.shadowColor = 'rgba(13,161,126,0.5)'
  this.context.shadowBlur = factors[9]
  this.context.fill()
  this.context.restore()
}
Marker1.prototype.drawWarnBattery = function (size, center) {
  let battery = this.data.battery
  this.context.save()
  this.context.translate(center[0] - size[0] * 12, center[1])
  this.context.miterLimit = 0
  this.context.fillStyle = 'white'
  this.context.strokeStyle = 'white'
  this.context.lineWidth = size[0]
  this.context.strokeRect(size[0] / 2, size[0] / 2, size[0] * 10, size[0] * 3 + size[1])
  this.context.translate(size[0] * 2, size[0] * 2)
  if (battery > 0) this.context.fillRect(0, 0, size[0], size[1])
  this.context.translate(size[0] * 2, 0)
  if (battery > 25) this.context.fillRect(0, 0, size[0], size[1])
  this.context.translate(size[0] * 2, 0)
  if (battery > 50) this.context.fillRect(0, 0, size[0], size[1])
  this.context.translate(size[0] * 2, 0)
  if (battery > 75) this.context.fillRect(0, 0, size[0], size[1])
  this.context.translate(size[0] * 3, 0)
  this.context.fillRect(0, 0, size[0], size[1])
  this.context.restore()
}
Marker1.prototype.drawWarnLamp = function (center) {
  let size = [util.dynamicPX(36) * this.scale, util.dynamicPX(38) * this.scale], baseWidth = util.dynamicPX(2) * this.scale, width = size[0], height = baseWidth, radius = height / 2
  this.context.save()
  this.context.fillStyle = '#E23A2C'
  this.context.strokeStyle = '#E23A2C'

  this.context.translate(...center)
  this.context.beginPath()
  this.context.lineTo(-width / 2 + height / 2, 0)
  this.context.arcTo(-width / 2, 0, -width / 2, -radius, radius)
  this.context.arcTo(-width / 2, -height, -width / 2 + radius, -height, radius)
  this.context.lineTo(width / 2 - radius, -height)
  this.context.arcTo(width / 2, -height, width / 2, -radius, radius)
  this.context.arcTo(width / 2, 0, width / 2 - radius, 0, radius)
  this.context.closePath()
  this.context.fill()

  this.context.translate(0, -size[1])
  radius = size[0] / 2
  width = baseWidth * 3
  height = baseWidth + baseWidth / 2
  this.context.lineWidth = height
  this.context.lineCap = "round"
  this.context.lineJoin = "round"

  this.context.beginPath()
  this.context.moveTo(-size[0] / 2, radius)
  this.context.lineTo(-size[0] / 2 + width, radius)
  this.context.closePath()
  this.context.stroke()

  this.context.beginPath()
  this.context.moveTo(-Math.cos(Math.PI * .25) * radius, radius - Math.sin(Math.PI * .25) * radius)
  this.context.lineTo(-Math.cos(Math.PI * .25) * (radius - width), radius - Math.sin(Math.PI * .25) * (radius - width))
  this.context.closePath()
  this.context.stroke()

  this.context.beginPath()
  this.context.moveTo(0, 0)
  this.context.lineTo(0, width)
  this.context.closePath()
  this.context.stroke()

  this.context.beginPath()
  this.context.moveTo(Math.cos(Math.PI * .25) * radius, radius - Math.sin(Math.PI * .25) * radius)
  this.context.lineTo(Math.cos(Math.PI * .25) * (radius - width), radius - Math.sin(Math.PI * .25) * (radius - width))
  this.context.closePath()
  this.context.stroke()

  this.context.beginPath()
  this.context.moveTo(size[0] / 2, radius)
  this.context.lineTo(size[0] / 2 - width, radius)
  this.context.closePath()
  this.context.stroke()

  this.context.translate(0, size[1] - baseWidth * 2)
  width = size[0] - ((baseWidth * 3) + (baseWidth + baseWidth / 2)) * 2
  height = size[1] - ((baseWidth * 3) + (baseWidth + baseWidth / 2)) - baseWidth * 2
  this.context.beginPath()
  this.context.lineTo(-width / 2 + baseWidth / 2, 0)
  this.context.arcTo(-width / 2, 0, -width / 2, -baseWidth / 2, baseWidth / 2)
  this.context.lineTo(-width / 2, -height + width / 2)
  this.context.arcTo(-width / 2, -height, 0, -height, width / 2)
  this.context.arcTo(width / 2, -height, width / 2, -height + width / 2, width / 2)
  this.context.lineTo(width / 2, -baseWidth / 2)
  this.context.arcTo(width / 2, 0, width / 2 - baseWidth / 2, 0, baseWidth / 2)
  this.context.closePath()
  this.context.fill()

  this.context.restore()

  let region = [center[0] - size[0] / 2, center[1] - size[1], ...size], w1 = util.dynamicPX(6) * this.scale, h1 = util.dynamicPX(12) * this.scale, w2 = w1 * 2, h2 = size[1]
  if (this.light == null) this.light = {}
  this.light.x1 = center[0]
  this.light.x2 = center[0]
  this.light.sp1 = util.dynamicPX(1) * this.scale
  this.light.sp2 = util.dynamicPX(2) * this.scale
  this.light.padding = util.dynamicPX(3) * this.scale
  this.region.push(region)
  this.animate('light', [region[0] - this.light.padding, region[1] - this.light.padding, region[2] + this.light.padding * 2, region[3] + this.light.padding * 2], () => {
    this.context.save()
    this.context.fillStyle = 'rgba(255,255,255,.5)'
    this.context.globalCompositeOperation = 'source-atop'

    this.context.beginPath()
    this.context.moveTo(this.light.x1, center[1] - baseWidth * 2)
    this.context.lineTo(this.light.x1 - w1 / 2, center[1] - baseWidth * 2)
    this.context.lineTo(this.light.x1 - w1 / 2, center[1] - baseWidth * 2 - h1 + w1 / 2)
    this.context.arcTo(this.light.x1 - w1 / 2, center[1] - baseWidth * 2 - h1, this.light.x1, center[1] - baseWidth * 2 - h1, w1 / 2)
    this.context.arcTo(this.light.x1 + w1 / 2, center[1] - baseWidth * 2 - h1, this.light.x1 + w1 / 2, center[1] - baseWidth * 2 - h1 + w1 / 2, w1 / 2)
    this.context.lineTo(this.light.x1 + w1 / 2, center[1] - baseWidth * 2)
    this.context.closePath()
    this.context.fill()

    this.context.beginPath()
    this.context.moveTo(this.light.x2, center[1] - baseWidth * 2)
    this.context.lineTo(this.light.x2 - w2 / 2, center[1] - baseWidth * 2)
    this.context.lineTo(this.light.x2 - w2 / 2, center[1] - baseWidth * 2 - h2 + w2 / 2)
    this.context.arcTo(this.light.x2 - w2 / 2, center[1] - baseWidth * 2 - h2, this.light.x2, center[1] - baseWidth * 2 - h2, w2 / 2)
    this.context.arcTo(this.light.x2 + w2 / 2, center[1] - baseWidth * 2 - h2, this.light.x2 + w2 / 2, center[1] - baseWidth * 2 - h2 + w2 / 2, w2 / 2)
    this.context.lineTo(this.light.x2 + w2 / 2, center[1] - baseWidth * 2)
    this.context.closePath()
    this.context.fill()

    this.context.restore()
    this.light.x1 = (this.light.x1 >= (center[0] + width / 2 + w1 / 2) ? (center[0] - width / 2 - w1 / 2) : (this.light.x1 + this.light.sp1))
    this.light.x2 = (this.light.x2 >= (center[0] + size[0] / 2 + w2 / 2) ? (center[0] - size[0] / 2 - w2 / 2) : (this.light.x2 + this.light.sp2))
  })
}
Marker1.prototype.drawWarnGlow = function () {
  if (this.glow == null) this.glow = {
    list: [],
    stepNumber: 100,
    lastTime: Date.now()
  }
  this.glow.maxRadius = util.dynamicPX(200) * this.scale
  this.glow.padding = util.dynamicPX(5) * this.scale
  this.animate('glow', [this.center[0] - this.glow.maxRadius - this.glow.padding, this.center[1] - this.glow.maxRadius - this.glow.padding, (this.glow.maxRadius + this.glow.padding) * 2, (this.glow.maxRadius + this.glow.padding) * 2], () => {
    let list = [...this.glow.list]
    for (let i = 0; i < list.length; i++) {
      if (this.glow.maxRadius - list[i].radius >= this.glow.maxRadius / this.glow.stepNumber) {
        list[i].radius += (this.glow.maxRadius / this.glow.stepNumber)
      } else list[i].radius = this.glow.maxRadius
      if (list[i].radius == this.glow.maxRadius) {
        list[i].opacity -= (1 / this.glow.stepNumber * 5)
        list[i].opacity = list[i].opacity <= 0 ? 0 : list[i].opacity
      }
      this.context.save()
      this.context.beginPath()
      this.context.arc(...this.center, list[i].radius, 0, Math.PI * 2, false)
      this.context.closePath()
      let gradient = this.context.createRadialGradient(...this.center, 0, ...this.center, list[i].radius)
      gradient.addColorStop(0, "rgba(202, 9, 12, .1)");
      gradient.addColorStop(.6, "rgba(202, 9, 12, .1)");
      gradient.addColorStop(1, "rgba(202, 9, 12, .26)");
      this.context.fillStyle = gradient
      this.context.globalCompositeOperation = 'destination-over'
      this.context.globalAlpha = list[i].opacity
      this.context.fill()
      this.context.restore()
      if (list[i].opacity <= 0) this.glow.list.splice(i, 1)
    }
    let lastTime = Date.now()
    if (lastTime - this.glow.lastTime >= 750 && this.glow.list.length < 5) {
      this.glow.list.push({opacity: 1, radius: 0})
      this.glow.lastTime = lastTime
    }
  })
}

function Marker2(data, context) {
  Marker.call(this, data, context, 2)
}

Marker2.prototype = {...Marker.prototype}
Marker2.prototype.constructor = Marker2
Marker2.prototype.drawIcon = function () {
  const icon = this.actived ? this.activedIcon : this.icon
  if (icon && icon instanceof Image) {
    let iconRenderWidth = util.dynamicPX(icon.width / 2) * this.scale, iconRenderHeight = util.dynamicPX(icon.height / 2) * this.scale,
      region = [this.center[0] - iconRenderWidth / 2, this.center[1], iconRenderWidth, iconRenderHeight]
    this.context.drawImage(icon, 0, 0, icon.width, icon.height, ...region)
    this.region.push(region)
    this.drawTitle()
  } else {
    let img = new Image()
    // img.src = require(`@/assets/image/map-marker-icon.${this.data.is_safe ? 'safety' : 'disaster'}${this.actived ? '.actived' : ''}.png`)
    img.src = require(`@/assets/img/homeicon.png`)
    img.onload = event => {
      if (this.actived) this.activedIcon = img
      else this.icon = img
      this.drawIcon()
    }
  }
}
Marker2.prototype.drawTitle = function () {
  const factors = [
    util.dynamicPX(6) * this.scale,  //圆角半径
    util.dynamicPX(10) * this.scale, //状态文字左间隔
    util.dynamicPX(6) * this.scale, //上右下左中间隔
    util.dynamicPX(16) * this.scale, //方位箭头宽度
    util.dynamicPX(8) * this.scale, //方位箭头高度
    util.dynamicPX(10) * this.scale, //阴影模糊半径
    util.dynamicPX(14) * this.scale, //文本字号
  ]
  this.drawTitleBg(factors)
  let region = this.region[this.region.length - 1]
  this.context.save()

  let name = `${this.data.name}，${this.data.phone_number}`
  let nameFontSize = factors[6]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameTextMetrics = this.context.measureText(name)
  this.context.fillStyle = '#606266'
  this.context.fillText(name, region[0] + factors[2], region[1] + factors[2] + nameFontSize - nameTextMetrics.actualBoundingBoxDescent)

  let status = this.data.is_safe ? '[安全区]' : '[受灾区]'
  let statusFontSize = factors[6]
  this.context.font = `bold ${statusFontSize}px ${this.font}`
  let statusTextMetrics = this.context.measureText(status)
  this.context.fillStyle = this.data.is_safe ? '#25CAD5' : '#E23A2C'
  this.context.fillText(status, region[0] + region[2] - factors[2] - statusTextMetrics.width, region[1] + factors[2] + statusFontSize - statusTextMetrics.actualBoundingBoxDescent)

  let point = `经度${this.data.longitude}，纬度${this.data.latitude}`
  let pointFontSize = factors[6]
  this.context.font = `${pointFontSize}px ${this.font}`
  let pointTextMetrics = this.context.measureText(point)
  this.context.fillStyle = '#909399'
  this.context.fillText(point, region[0] + factors[2], region[1] + region[3] - factors[2] - pointTextMetrics.actualBoundingBoxDescent)

  this.context.restore()
}
Marker2.prototype.drawTitleBg = function (factors) {
  this.context.save()

  let name = `${this.data.name}，${this.data.phone_number}`
  let nameFontSize = factors[6]
  this.context.font = `${nameFontSize}px ${this.font}`
  let nameWidth = this.context.measureText(name).width

  let status = this.data.is_safe ? '[安全区]' : '[受灾区]'
  let statusFontSize = factors[6]
  this.context.font = `bold ${statusFontSize}px ${this.font}`
  let statusWidth = this.context.measureText(status).width

  let point = `经度${this.data.longitude}，纬度${this.data.latitude}`
  let pointFontSize = factors[6]
  this.context.font = `${pointFontSize}px ${this.font}`
  let pointWidth = this.context.measureText(point).width

  let width = Math.max(nameWidth + factors[1] + statusWidth + factors[2] * 2, pointWidth + factors[2] * 2)
  let height = statusFontSize + pointFontSize + factors[2] * 4  //上下内边距
  let radius = factors[0]
  let direction = [factors[3], factors[4]]  //方位箭头尺寸

  this.context.beginPath()
  this.context.moveTo(...this.center)
  this.context.lineTo(this.center[0] - direction[0] / 2, this.center[1] - direction[1])
  this.context.lineTo(this.center[0] - width / 2, this.center[1] - direction[1])
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1] - direction[1], this.center[0] - width / 2 - radius, this.center[1] - direction[1] - radius, radius)
  this.context.lineTo(this.center[0] - width / 2 - radius, this.center[1] - direction[1] - height - radius)
  this.context.arcTo(this.center[0] - width / 2 - radius, this.center[1] - direction[1] - height - radius * 2, this.center[0] - width / 2, this.center[1] - direction[1] - height - radius * 2, radius)
  this.context.lineTo(this.center[0] + width / 2, this.center[1] - direction[1] - height - radius * 2)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1] - direction[1] - height - radius * 2, this.center[0] + width / 2 + radius, this.center[1] - direction[1] - height - radius, radius)
  this.context.lineTo(this.center[0] + width / 2 + radius, this.center[1] - direction[1] - radius)
  this.context.arcTo(this.center[0] + width / 2 + radius, this.center[1] - direction[1], this.center[0] + width / 2, this.center[1] - direction[1], radius)
  this.context.lineTo(this.center[0] + direction[0] / 2, this.center[1] - direction[1])
  this.context.lineTo(...this.center)
  this.context.closePath()
  this.region.push([this.center[0] - width / 2, this.center[1] - direction[1] - height - radius, width, height])
  this.context.fillStyle = this.actived ? '#DCDFE6' : 'white'
  this.context.shadowColor = 'rgba(216,216,216,0.51)'
  this.context.shadowBlur = factors[5]
  this.context.fill()
  this.context.restore()
}

function MapHandler(AMap, Map) {
  this.aMap = AMap
  this.map = Map
  this.renderType = 1
  this.markerList = []
  this.canvas = document.createElement('canvas')
  this.context = this.canvas.getContext('2d')
  this.map.add(new AMap.CustomLayer(this.canvas, {zooms: this.map.getZooms(), alwaysRender: false, render: this.render.bind(this)}))
  util.resize(() => {
    this.canvas.width = this.map.getSize().width
    this.canvas.height = this.map.getSize().height
    this.render()
  })
  this.canvas.addEventListener('mousemove', event => {
    let marker = this.hasMarkerInPoint(this.markerList, [event.x, event.y])
    this.canvas.style.cursor = marker ? 'pointer' : 'auto'
  }, false)
  this.canvas.addEventListener('click', event => {
    let marker = this.hasMarkerInPoint(this.markerList, [event.x, event.y])
    if (marker) {
      let {onClick, ...data} = marker.data
      if (onClick && onClick instanceof Function) onClick(data)
      this.setActiveMarker(marker)
      this.render()
    }
  }, false)
}

MapHandler.prototype.hasMarkerInPoint = function (markerList, point) {
  let result = null
  for (let i = 0; i < markerList.length; i++) {
    if (markerList[i].region && markerList[i].region instanceof Array) {
      for (let r = 0; r < markerList[i].region.length; r++) {
        let x1 = markerList[i].region[r][0], y1 = markerList[i].region[r][1],
          x2 = markerList[i].region[r][0] + markerList[i].region[r][2], y2 = markerList[i].region[r][1] + markerList[i].region[r][3]
        if (point[0] >= x1 && point[0] <= x2 && point[1] >= y1 && point[1] <= y2) {
          result = markerList[i]
          break
        } else continue
      }
      if (result) break
      else continue
    } else continue
  }
  return result
}
MapHandler.prototype.render = function () {
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
  const markerList = this.markerList.filter(marker => marker.type == this.renderType)
  markerList.forEach(marker => {
    marker.render(this.getMarkerScale(), this.getMarkerCenter(marker))
  })
}
MapHandler.prototype.clearActiveMarker = function () {
  this.markerList.forEach(marker => {
    marker.actived = false
  })
  this.render()
}
MapHandler.prototype.setActiveMarker = function (marker) {
  this.markerList.forEach(item => {
    if (item == marker) item.actived = true
    else item.actived = false
  })
}
MapHandler.prototype.getMarkerScale = function () {
  return (this.map.getZoom() - this.map.getZooms()[0]) / (this.map.getZooms()[1] - this.map.getZooms()[0])
}
MapHandler.prototype.getMarkerCenter = function (marker) {
  const point = this.map.lngLatToContainer([marker.data.longitude, marker.data.latitude])
  return [point.x, point.y]
}
MapHandler.prototype.setRenderType = function (type) {
  this.renderType = type
  this.markerList = this.markerList.filter((marker, index, origin) => {
    if (marker.type == this.renderType) return true
    else {
      util.stopAnimation(marker.animationId)
      delete origin[index]
      return false
    }
  })
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
}
MapHandler.prototype.addMarkers = function (dataList, type) {
  dataList.forEach(item => {
    if (this.markerList.filter(marker => marker.type == type).map(marker => marker.data.id).includes(item.id)) return
    else {
      const marker = type == 2 ? new Marker2(item, this.context) : type == 1 ? new Marker1(item, this.context) : null
      if (marker != null) this.markerList.push(marker)
    }
  })
  this.render()
}
export default MapHandler
